/* This file is part of swapper project
 *
 * Copyright (C) 2020 The Swapper Project Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.swapper.json.spi.supports.util;

import com.swapper.json.*;

import java.lang.reflect.Type;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * The {@link Calendar} wrapper factory.
 */
public enum CalendarWrapperFactory implements JsonWrapperFactory {
  INSTANCE;

  @SuppressWarnings("unchecked")
  @Override
  public <T> JsonWrapper<T> create(JsonContext context, Type type) {
    return type == Calendar.class ? (JsonWrapper<T>) Wrapper.INSTANCE : null;
  }

  public enum Wrapper implements JsonWrapper<Calendar> {
    INSTANCE;

    private static final String YEAR = "year";
    private static final String MONTH = "month";
    private static final String DAY_OF_MONTH = "dayOfMonth";
    private static final String HOUR_OF_DAY = "hourOfDay";
    private static final String MINUTE = "minute";
    private static final String SECOND = "second";

    @Override
    public JsonValue wrap(Calendar value) {
      if (value == null) {
        return JsonValue.NULL;
      }
      JsonObject jsonObject = new JsonObject(6);
      jsonObject.put(YEAR, JsonNumber.valueOf(value.get(Calendar.YEAR)));
      jsonObject.put(MONTH, JsonNumber.valueOf(value.get(Calendar.MONTH)));
      jsonObject.put(DAY_OF_MONTH, JsonNumber.valueOf(value.get(Calendar.DAY_OF_MONTH)));
      jsonObject.put(HOUR_OF_DAY, JsonNumber.valueOf(value.get(Calendar.HOUR_OF_DAY)));
      jsonObject.put(MINUTE, JsonNumber.valueOf(value.get(Calendar.MINUTE)));
      jsonObject.put(SECOND, JsonNumber.valueOf(value.get(Calendar.SECOND)));
      return jsonObject;
    }

    @SuppressWarnings("all")
    @Override
    public Calendar unwrap(JsonValue value) {
      if (JsonValue.NULL.equals(value)) {
        return null;
      }
      JsonObject jsonObject = value.toJsonObject();
      return new GregorianCalendar(
        jsonObject.getInteger(YEAR),
        jsonObject.getInteger(MONTH),
        jsonObject.getInteger(DAY_OF_MONTH),
        jsonObject.getInteger(HOUR_OF_DAY),
        jsonObject.getInteger(MINUTE),
        jsonObject.getInteger(SECOND)
      );
    }
  }
}
